package com.cby.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cby.exception.CbyException;
import com.cby.other.R;
import com.cby.user.entity.CbyUser;
import com.cby.user.entity.query.CbyUserQuery;
import com.cby.user.entity.vo.CbyUserTableVo;
import com.cby.user.entity.vo.CbyUserVo;
import com.cby.user.helper.SpringHelper;
import com.cby.user.mapper.CbyUserMapper;
import com.cby.user.service.CbyIdentityService;
import com.cby.user.service.CbyUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cby.user.test3D.*;
import com.cby.user.util.JwtUtil;
import com.cby.user.util.RandomUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.mail.internet.MimeMessage;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wskh
 * @since 2021-11-03
 */
@Service
public class CbyUserServiceImpl extends ServiceImpl<CbyUserMapper, CbyUser> implements CbyUserService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private CbyUserService userService;
    @Autowired
    private CbyIdentityService identityService;

    // 用户注册
    @Override
    public R register(CbyUserVo cbyUserVo) {
        try {
            //获取注册信息，进行校验
            String name = cbyUserVo.getName();
            String nickName = cbyUserVo.getNickName();
            String password = cbyUserVo.getPassword();
            String verificationCode = cbyUserVo.getVerificationCode();
            String email = cbyUserVo.getEmail();
            String phone = cbyUserVo.getPhone();
            String identityId = cbyUserVo.getIdentityId();
            String detail = cbyUserVo.getDetail();
            cbyUserVo.setId(UUID.randomUUID().toString());

            //校验参数
            if(StringUtils.isEmpty(name) ||
                    StringUtils.isEmpty(nickName) ||
                    StringUtils.isEmpty(password) ||
                    StringUtils.isEmpty(verificationCode) ||
                    StringUtils.isEmpty(email) ||
                    StringUtils.isEmpty(phone) ||
                    StringUtils.isEmpty(identityId) ||
                    StringUtils.isEmpty(detail)){
                throw new CbyException(500,"参数不能为空");
            }

            //校验校验验证码
            //从redis获取发送的验证码
            String phoneCode = redisTemplate.opsForValue().get(phone);
            String emailCode = redisTemplate.opsForValue().get(email);
            if(!verificationCode.equals(phoneCode)&&!verificationCode.equals(emailCode)) {
                throw new CbyException(500,"验证码有误");
            }

            //查询数据库中是否存在相同的手机号码
            int count = baseMapper.selectCount(new
                    QueryWrapper<CbyUser>().eq("phone", phone));
            if(count > 0) {
                throw new CbyException(500,"已经存在相同的手机号码");
            }

            //添加注册信息到数据库
            CbyUser user = new CbyUser();
            BeanUtils.copyProperties(cbyUserVo,user);

            baseMapper.insert(user);

        }catch (Exception e){
            e.printStackTrace();
            return R.error("注册失败");
        }
        return R.ok("注册成功");
    }

    // 登录验证
    @Override
    public R login(String name, String password) {
        List<CbyUser> allUser = userService.list();
//        return R.ok("登陆成功").data("token","ddd");
        for (CbyUser user : allUser) {
            if (user.getName().equals(name) && user.getPassword().equals(password)) {
                String identityId = user.getIdentityId();
                if(identityService.getById(identityId).equals("被禁用者")){
                    // 如果用户被禁用了
                    return R.error("登录失败，用户名被禁用!");
                }else if(!identityService.getById(identityId).equals("管理员")&&!"5".equals(identityId)){
                    // 如果用户不是管理员 那么不给登录
                    return R.error("登录失败，非管理员!");
                }
                // 验证通过
                String token = JwtUtil.createToken(user.getId());
                // 将token存入redis中 (.set(K,V),过期时间,时间单位) 3小时过期
                redisTemplate.opsForValue().set("userToken"+token, JSON.toJSONString(user),3, TimeUnit.HOURS);
                System.out.println("登陆成功");
                return R.ok("登陆成功").data("token",token);
            }
        }
        return R.error("登录失败，用户名或密码错误!");
    }

    // 发送验证码
    @Override
    public R sendVerificationCode(String email) {
        try{
            // 先判断redis中是否已经存在验证码 如果存在则无需生成
            String emailCode = redisTemplate.opsForValue().get(email);
            if(!StringUtils.isEmpty(emailCode)){
                return R.ok("验证码已发送");
            }
            // 随机生成6位数的验证码
            String sixBitRandom = RandomUtil.getSixBitRandom();
            // 一个复杂的邮件
            JavaMailSenderImpl javaMailSender = SpringHelper.getBean(JavaMailSenderImpl.class);
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            // 组装
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "utf-8");
            // 主题
            helper.setSubject("您好，欢迎注册cby科技有限公司的算法集成系统 "+new Date());
            // 内容
            StringBuilder text = new StringBuilder("您的验证码如下(3分钟内有效)：");
            text.append(sixBitRandom);
            helper.setText(text.toString(),true);
            //发给谁
            helper.setTo(email);
            //来自哪
            helper.setFrom("1187560563@qq.com");
            // 发送！
            javaMailSender.send(mimeMessage);
            // 将验证码存入redis 3分钟内有效
            redisTemplate.opsForValue().set(email, sixBitRandom,3, TimeUnit.MINUTES);
        }catch (Exception e){
            e.printStackTrace();
            return R.error("发送失败");
        }
        return R.ok("发送成功");
    }

    @Override
    public R retrievePassword(String phone, String email) {
        try{
            // 先判断是否存在此用户
            QueryWrapper<CbyUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("phone",phone);
            queryWrapper.eq("email",email);
            CbyUser user = userService.getOne(queryWrapper);
            if(user==null){
                return R.error("手机号或邮箱输入有误");
            }
            // 一个复杂的邮件
            JavaMailSenderImpl javaMailSender = SpringHelper.getBean(JavaMailSenderImpl.class);
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            // 组装
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "utf-8");
            // 主题
            helper.setSubject("您好，cby科技有限公司的算法集成系统为您提供找回密码服务 "+new Date());
            // 内容
            StringBuilder text = new StringBuilder("您的密码如下：");
            text.append(user.getPassword());
            helper.setText(text.toString(),true);
            // 发给谁
            helper.setTo(email);
            // 来自哪
            helper.setFrom("1187560563@qq.com");
            // 发送！
            javaMailSender.send(mimeMessage);
        }catch (Exception e){
            e.printStackTrace();
            return R.error("找回密码失败");
        }
        return R.ok("邮件发送成功");
    }

    @Override
    public R queryUser(long current, long limit, CbyUserQuery cbyUserQuery) {
        // 创建page对象
        Page<CbyUser> userPage = new Page<>(current,limit);
        // 构建条件
        QueryWrapper<CbyUser> queryWrapper = new QueryWrapper<>();
        String name = cbyUserQuery.getName();
        String nickName = cbyUserQuery.getNickName();
        String email = cbyUserQuery.getEmail();
        String phone = cbyUserQuery.getPhone();
        String identityId = cbyUserQuery.getIdentityId();
        Date begin = cbyUserQuery.getBegin();
        Date end = cbyUserQuery.getEnd();

        // 按照添加时间排序
        queryWrapper.orderByDesc("insert_time");
        if (!StringUtils.isEmpty(name)) {
            queryWrapper.like("name", name);
        }
        if (!StringUtils.isEmpty(nickName) ) {
            queryWrapper.like("nick_name", nickName);
        }
        if (!StringUtils.isEmpty(email)) {
            queryWrapper.like("email", email);
        }
        if (!StringUtils.isEmpty(phone)) {
            queryWrapper.like("phone", phone);
        }
        if (!StringUtils.isEmpty(identityId)) {
            queryWrapper.like("identity_id", identityId);
        }
        if (!StringUtils.isEmpty(begin)) {
            queryWrapper.ge("insert_time", begin);
        }
        if (!StringUtils.isEmpty(end)) {
            queryWrapper.le("insert_time", end);
        }
        // 调用方法实现 分页条件查询
        IPage<CbyUser> page = userService.page(userPage, queryWrapper);
        List<CbyUser> records = page.getRecords();

        List<CbyUserTableVo> userTableVoList = new ArrayList<>();
        for (CbyUser user : records) {
            CbyUserTableVo userTableVo = new CbyUserTableVo();
            BeanUtils.copyProperties(user,userTableVo);
            userTableVo.setIdentity(identityService.getById(userTableVo.getIdentityId()).getName());
            userTableVoList.add(userTableVo);
        }
        return R.ok().data("total",page.getTotal()).data("rows",userTableVoList);
    }

    @Override
    public R test3D() {
        try {
            String path = "D:\\IDEA_PaidVersion\\cby\\back\\cby_user_7001\\src\\main\\java\\com\\cby\\user\\test3D\\data\\instance.txt";
            DataUtil dataUtil = new DataUtil(1f);
            // 给定20s计算时间
            SinglePacking model = new SinglePacking(dataUtil.read(path),200L*1000L);
            Solution solution = model.solve();
            System.out.println("一共有"+solution.getTotalBoxNum()+"个箱子，装载了"+solution.getPlaceBoxes().length+"个");
            System.out.println("容器利用率为："+solution.getPackRate());
            // 转化为cubeList
            List<Cube> cubeList = new ArrayList<>();
            PlaceBox[] placeBoxes = solution.getPlaceBoxes();
            for (int i = 0; i < placeBoxes.length; i++) {
                PlaceBox placeBox = placeBoxes[i];
                // 坐标
                double x = placeBox.getX()+placeBox.getL()/2.0;
                double y = placeBox.getY()+placeBox.getW()/2.0;
                double z = placeBox.getZ()+placeBox.getH()/2.0;
                // 长宽高
                double l = placeBox.getL();
                double w = placeBox.getW();
                double h = placeBox.getH();
                Cube cube = new Cube(x,y,z,l,w,h);
                cubeList.add(cube);
            }
            return R.ok("test3D成功").data("cubeList",cubeList);
        }catch (Exception e){
            e.printStackTrace();
            return R.error("test3D失败");
        }
    }

    @Override
    public R getPlotData() {
        List<Date> xdata = new ArrayList<>();
        List<Integer> ydata = new ArrayList<>();
        List<CbyUser> userList = userService.list();
        for (CbyUser user : userList) {
            Date insertTime = user.getInsertTime();
            boolean b = false;
            for (int i = 0; i < xdata.size(); i++) {
                if(xdata.get(i).getTime()==user.getInsertTime().getTime()){
                    b = true;
                    ydata.set(i,ydata.get(i)+1);
                    i = xdata.size();
                }
            }
            if(!b){
                xdata.add(new Date(insertTime.getTime()));
                ydata.add(1);
            }
        }
        return R.ok().data("xdata",xdata).data("ydata",ydata);
    }
}
